package org.anachronos.jeep.ui.trace;

import org.anachronos.jeep.model.trace.DocumentRoot;
import org.anachronos.jeep.model.trace.Invocation;
import org.anachronos.jeep.model.trace.TracePackage;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.MultiList;
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
import org.eclipse.core.databinding.property.list.IListProperty;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.emf.databinding.FeaturePath;
import org.eclipse.emf.databinding.IEMFListProperty;
import org.eclipse.jface.viewers.ViewerFilter;

public class TraceTreeFactory implements IObservableFactory {
	private final IEMFListProperty threadCallStackObservables = 
		EMFProperties.multiList(TracePackage.Literals.INVOCATION__METHOD_INVOCATION, 
			TracePackage.Literals.INVOCATION__SQL_STATEMENT_EXECUTION,
			TracePackage.Literals.INVOCATION__TRANSACTION);
	private final IListProperty documentRootObservables;
	private final ViewerFilter viewerFilter;
	
	private final static IEMFListProperty THREADS_LIST = 
		EMFProperties.list(FeaturePath.fromList(
				TracePackage.Literals.DOCUMENT_ROOT__TRACE,
				TracePackage.Literals.TRACE__CALL_STACKS, 
				TracePackage.Literals.CALL_STACKS_TYPE__CALL_STACK));

	private final static IEMFListProperty TRACE_VALUE = 
		EMFProperties.list(FeaturePath.fromList(
				TracePackage.Literals.DOCUMENT_ROOT__TRACE,
				TracePackage.Literals.TRACE__MERGED_CALL_STACK));
	

	private TraceTreeFactory(final IListProperty documentRootObservables, final ViewerFilter viewerFilter) {
		this.documentRootObservables = documentRootObservables;
		this.viewerFilter = viewerFilter;
	}
	
	public static TraceTreeFactory createTraceThreadTreeFactory(final ViewerFilter viewerFilter) {
		return new TraceTreeFactory(THREADS_LIST, viewerFilter);
	}

	public static TraceTreeFactory createCallStackTreeFactory(final ViewerFilter viewerFilter) {
		return new TraceTreeFactory(TRACE_VALUE, viewerFilter);
	}

	
	@Override
	public IObservable createObservable(final Object target) {
		if (target instanceof IObservableList) {
			return (IObservableList) target;
		} 
		if (target instanceof DocumentRoot) {
			final ViewerFilterObservableList traceFilterObservableList = 
				new ViewerFilterObservableList(viewerFilter);
			final IObservableList documentRootObservableList = 
				documentRootObservables.observe(target);
			final IObservableList[] oberservableLists = 
				new IObservableList[] { documentRootObservableList, traceFilterObservableList };
			return new MultiList(oberservableLists);
		}
		if (target instanceof Invocation) {
			return threadCallStackObservables.observe(target);
		}
		return null;
	}
}
